/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { ts, NodePredicate, native, HomeCheckHint } from 'qvog-dsl';

const SEVERITY = 2;
const DOC_PATH = 'docs/ban-types.md';
const DESCRIPTION = 'Disallow certain types.';

// 定义需要检查的节点类型
const TypeNode: NodePredicate<ts.Node> = {
  is(node: ts.Node): node is ts.Node {
    return ts.isTypeReferenceNode(node) || 
           ts.isTypeLiteralNode(node) ||
           ts.isTupleTypeNode(node) ||
           ts.isTypeAliasDeclaration(node) ||
           ts.isInterfaceDeclaration(node) ||
           ts.isClassDeclaration(node);
  }
};

// 默认禁用的类型及其配置
const defaultTypes = {
  String: { message: 'Use string instead', fixWith: 'string' },
  Boolean: { message: 'Use boolean instead', fixWith: 'boolean' },
  Number: { message: 'Use number instead', fixWith: 'number' },
  Symbol: { message: 'Use symbol instead', fixWith: 'symbol' },
  BigInt: { message: 'Use bigint instead', fixWith: 'bigint' },
  Function: { 
    message: 'The `Function` type accepts any function-like value.\nIt provides no type safety when calling the function...' 
  },
  Object: { 
    message: "The `Object` type actually means 'any non-nullish value'...",
    suggest: ['object', 'unknown', 'NonNullable<unknown>']
  },
  '{}': {
    message: "`{}` actually means 'any non-nullish value'...",
    suggest: ['object', 'unknown', 'Record<string, never>', 'NonNullable<unknown>']
  }
};

// 辅助函数：去除字符串中的空格
function removeKeySpaces(str: string): string {
  return str.replace(/\s/g, '');
}

export default native<HomeCheckHint>()()
  .match(TypeNode)
  .when((node: ts.Node): boolean => {
    // 获取类型文本
    const typeText = removeKeySpaces(node.getText());
    
    // 检查是否是禁用类型
    if (typeText in defaultTypes) {
      return true;
    }
    
    // 如果是类型引用节点，检查其类型名称
    if (ts.isTypeReferenceNode(node) && ts.isIdentifier(node.typeName)) {
      const typeName = removeKeySpaces(node.typeName.text);
      return typeName in defaultTypes;
    }
    
    return false;
  })
  .report({
    severity: SEVERITY,
    description: DESCRIPTION,
    docPath: DOC_PATH
  });